﻿#include "BitMap.h"

BitMap::BitMap():BitMap(0)
{
}

BitMap::BitMap(int maxNum)
{
	setMaxNum(maxNum);
}

int BitMap::getMaxNum() const
{
	if (_bytes.empty())
		return 0;
	return _bytes.size() * 8-1;
}

int BitMap::getBytesSize() const
{
	return _bytes.size();
}

void BitMap::setMaxNum(int maxNum)
{
	const int maxNumInByte = maxNum + 1;
	int bytesSize = 1;
	if(maxNumInByte >0)
		bytesSize = maxNumInByte / 8 + ((maxNumInByte % 8) > 0 ? 1 : 0);
	_bytes.resize(bytesSize);
}

void BitMap::setNumFlag(int num, bool flag)
{
	if (num<0 || num>getMaxNum())
		return;

	auto& byteContainNum=  _bytes[num >> 3];
	if (flag)
		byteContainNum |= 1 << (num % 8);
	else
		byteContainNum &= ~(1 << (num % 8));
}

bool BitMap::getNumFlag(int num)
{
	if (num<0 || num>getMaxNum())
		return false;

	auto& byteContainNum = _bytes[num >> 3];
	return (byteContainNum & (1 << (num % 8)))!=0;
}

void BitMap::resetFlags()
{
	if(!_bytes.empty())
		memset(&_bytes.front(), 0, _bytes.size());
	//for (auto& byte : _bytes)
	//	byte = 0;
}

#ifdef DEV_TEST
#include <gtest/gtest.h>
TEST(BitMapTest, getMaxNum_Default)
{
	BitMap bitMap;
	EXPECT_EQ(bitMap.getMaxNum(), 7);
	EXPECT_EQ(bitMap.getBytesSize(), 1);
}

TEST(BitMapTest, setMaxNum)
{
	BitMap bitMap;

	//需要2个字节容纳8
	{
		bitMap.setMaxNum(8);
		EXPECT_EQ(bitMap.getMaxNum(), 15);
		EXPECT_EQ(bitMap.getBytesSize(), 2);
	}

	//需要1个字节容纳4
	{
		bitMap.setMaxNum(4);
		EXPECT_EQ(bitMap.getMaxNum(), 7);
		EXPECT_EQ(bitMap.getBytesSize(), 1);
	}
}

TEST(BitMapTest,numFlag_RandGetAndSet)
{
	BitMap bitMap;
	constexpr int testTimes = 100;
	for(int i=0;i<testTimes;++i)
	{
		const int maxNum = TestingUtil::randIntBetween(100, 500);
		bitMap.setMaxNum(maxNum);

		std::unordered_set<int> checkSet;
		for(int j=0;j<3000;++j)
		{
			const int randNum = TestingUtil::randIntBetween(0, maxNum);
			const bool hasFlag = TestingUtil::randPercentage(0.5f);
			bitMap.setNumFlag(randNum, hasFlag);

			if (hasFlag)
				checkSet.insert(randNum);
			else
				checkSet.erase(randNum);

			EXPECT_EQ(bitMap.getNumFlag(randNum), checkSet.count(randNum) > 0);
		}

		//在checkSet中剩余的，在bitMap中也应该都有flag
		for(auto it=checkSet.begin();it!=checkSet.end();++it)
		{
			const int leftNum = *it;
			EXPECT_TRUE(bitMap.getNumFlag(leftNum));
		}
	}
}

TEST(BitMapTest,numFlag_SpecialGetAndSet)
{
	BitMap bitmap;

	//未设置标识前应该都为false
	bitmap.setMaxNum(1780023921);
	EXPECT_FALSE(bitmap.getNumFlag(0));
	EXPECT_FALSE(bitmap.getNumFlag(1780023921));

	//有设置标识后变为true
	bitmap.setNumFlag(0, true);
	bitmap.setNumFlag(1780023921, true);
	EXPECT_TRUE(bitmap.getNumFlag(0));
	EXPECT_TRUE(bitmap.getNumFlag(1780023921));

	//不在位图范围内的数字
	EXPECT_FALSE(bitmap.getNumFlag(-1));
	EXPECT_FALSE(bitmap.getNumFlag(1780023922));

	//清空位图的所有标识后都变为false
	bitmap.resetFlags();
	EXPECT_FALSE(bitmap.getNumFlag(0));
	EXPECT_FALSE(bitmap.getNumFlag(1780023921));
}
#endif